/**
 * Copyright (c) 2021 Wei-Lun Hsu. All Rights Reserved.
 */
/** @file zb32l03x_hal_cryp.h
 *
 * @author Wei-Lun Hsu
 * @version 0.1
 * @date 2021/09/27
 * @license
 * @description
 */

#ifndef __ZB32L03x_HAL_CRYP_H
#define __ZB32L03x_HAL_CRYP_H

#ifdef __cplusplus
extern "C" {
#endif

#include "zb32l03x_hal_def.h"

/** @addtogroup ZB32L03x_HAL_Driver
  * @{
  */

/** @addtogroup CRYP
  * @{
  */
//=============================================================================
//                  Constant Definition
//=============================================================================
/** @defgroup CRYP_Exported_Constants CRYP Exported Constants
  * @{
  */

#define AES_IRQn                AES_OWIRE_IRQn
#define AES_IRQHandler          AES_OWIRE_IRQHandler

/**
 *  state of CRYP
 */
typedef enum
{
    HAL_CRYP_STATE_RESET             = 0x00U,  /*!< CRYP not yet initialized or disabled  */
    HAL_CRYP_STATE_READY             = 0x01U,  /*!< CRYP initialized and ready for use    */
    HAL_CRYP_STATE_BUSY              = 0x02U,  /*!< CRYP internal processing is ongoing   */
    HAL_CRYP_STATE_TIMEOUT           = 0x03U,  /*!< CRYP timeout state                    */
    HAL_CRYP_STATE_ERROR             = 0x04U   /*!< CRYP error state                      */

} HAL_CRYP_State_TypeDef;

/**
 *   HAL CRYP phase definition

 */
typedef enum
{
    HAL_CRYP_PHASE_READY            = 0x01U,    /*!< CRYP peripheral is ready for initialization. */
    HAL_CRYP_PHASE_PROCESS          = 0x02U,    /*!< CRYP peripheral is in processing phase */
} HAL_Phase_TypeDef;


/**
 *  The mode of CRYP
 */
typedef enum
{
    HAL_CRYP_MODE_NONE  = 0,
    HAL_CRYP_MODE_ECB,          /**< Electronic codebook   */
    HAL_CRYP_MODE_CBC,          /**< Cipher-block chaining */
    HAL_CRYP_MODE_CTR,          /**< Counter mode          */
} HAL_CRYP_Mode_TypeDef;

/**
 *  The trigger mode
 */
typedef enum
{
    HAL_CRYP_TRIGGER_UNKNOWN    = 0,    /**< default */
    HAL_CRYP_TRIGGER_POLLING,           /**< Processing functions by algorithm using polling mode */
    HAL_CRYP_TRIGGER_IRQ,               /**< Processing functions by algorithm using interrupt mode */
    HAL_CRYP_TRIGGER_DMA,               /**< Processing functions by algorithm using DMA mode */
} HAL_CRYP_Trigger_TypeDef;


/**
 *  Data type for data in/out to/from the cryptographic block
 */
typedef enum
{
    HAL_CRYP_Data_32B = AES_CR_DATATYPE_NONE      << AES_CR_DATATYPE_Pos,
    HAL_CRYP_Data_16B = AES_CR_DATATYPE_HALF_WORD << AES_CR_DATATYPE_Pos,
    HAL_CRYP_Data_8B  = AES_CR_DATATYPE_BYTE      << AES_CR_DATATYPE_Pos,
    HAL_CRYP_Data_1B  = AES_CR_DATATYPE_BIT       << AES_CR_DATATYPE_Pos,
} HAL_CRYP_Data_TypeDef;


/**
 *  The Algorithm Mode of CRYP
 */
typedef enum
{
    HAL_CRYP_ALGO_MODE_DIRECTION              = (AES_CR_MODE_MODE_4 << AES_CR_MODE_Pos) | (AES_CR_CHMOD_RSVD << AES_CR_CHMOD_Pos),
    HAL_CRYP_ALGO_MODE_AES_ECB_ENCRYPT        = (AES_CR_MODE_MODE_1 << AES_CR_MODE_Pos) | (AES_CR_CHMOD_EBC << AES_CR_CHMOD_Pos),
    HAL_CRYP_ALGO_MODE_AES_ECB_KEYDERDECRYPT  = (AES_CR_MODE_MODE_4 << AES_CR_MODE_Pos) | (AES_CR_CHMOD_EBC << AES_CR_CHMOD_Pos),
    HAL_CRYP_ALGO_MODE_AES_CBC_ENCRYPT        = (AES_CR_MODE_MODE_1 << AES_CR_MODE_Pos) | (AES_CR_CHMOD_CBC << AES_CR_CHMOD_Pos),
    HAL_CRYP_ALGO_MODE_AES_CBC_KEYDERDECRYPT  = (AES_CR_MODE_MODE_4 << AES_CR_MODE_Pos) | (AES_CR_CHMOD_CBC << AES_CR_CHMOD_Pos),
    HAL_CRYP_ALGO_MODE_AES_CTR_ENCRYPT        = (AES_CR_MODE_MODE_1 << AES_CR_MODE_Pos) | (AES_CR_CHMOD_CTR << AES_CR_CHMOD_Pos),
    HAL_CRYP_ALGO_MODE_AES_CTR_DECRYPT        = (AES_CR_MODE_MODE_3 << AES_CR_MODE_Pos) | (AES_CR_CHMOD_CTR << AES_CR_CHMOD_Pos),
    HAL_CRYP_ALGO_MODE_CHAIN_MASK             = (AES_CR_MODE | AES_CR_CHMOD),

} HAL_CRYP_ALGO_MODE_TypeDef;

/**
 *   AES Interrupts type of CRYP
 */
typedef enum
{
    HAL_CRYP_IT_CC      = AES_CR_CCFIE,  /*!< Computation Complete interrupt */
    HAL_CRYP_IT_ERR     = AES_CR_ERRIE, /*!< Error interrupt                */
} HAL_CRYP_IT_TypeDef;

/**
 *  CRYP interrupt flags
 */
typedef enum
{
    HAL_CRYP_FLAG_CCF       = AES_SR_CCF,    /*!< Computation Complete Flag */
    HAL_CRYP_FLAG_RDERR     = AES_SR_RDERR,  /*!< Read Error Flag           */
    HAL_CRYP_FLAG_WRERR     = AES_SR_WRERR,  /*!< Write Error Flag          */
} HAL_CRYP_FLAG_TypeDef;


typedef enum
{
    HAL_CRYP_CLRFLAG_CCF    = AES_CR_CCFC,  /*!< Computation Complete Flag Clear */
    HAL_CRYP_CLRFLAG_ERR    = AES_CR_ERRC,  /*!< Read/Write Error Clear          */

} HAL_CRYP_CLRFLAG_TypeDef;

/**
  * @}
  */ /* End of group CRYP_Exported_Constants */


//=============================================================================
//                  Structure Definition
//=============================================================================
/** @defgroup CRYP_Exported_Types CRYP Exported Types
  * @{
  */

/**
 *  @brief  CRYP Initial Structure definition
 */
typedef struct
{
    HAL_CRYP_Data_TypeDef   DataType;   /*!< 32-bit data, 16-bit data, 8-bit data or 1-bit string.
                                            This parameter can be a value of @ref HAL_CRYP_Data_TypeDef */

    uint32_t    *pKey;                  /*!< The key used for encryption/decryption */
    uint32_t    *pInitVect;             /*!< The initialization vector used also as initialization counter in CTR mode */

} CRYP_Init_TypeDef;

/**
 *  The handle of CRYP
 */
typedef struct
{
    AES_TypeDef                     *Instance;  /*!< Register base address    */
    CRYP_Init_TypeDef               Init;       /*!< CRYP required parameters */

    HAL_CRYP_Trigger_TypeDef        TriggerType; /*!<  The trigger type. This parameter can be a value of @ref HAL_CRYP_Trigger_TypeDef */
    __IO HAL_CRYP_State_TypeDef     State;      /*!< CRYP peripheral status   */
    HAL_Phase_TypeDef               Phase;      /*!< CRYP peripheral phase    */
    HAL_LockTypeDef                 Lock;       /*!< CRYP locking object      */

    /* internal using */
    uint32_t                        *pCrypInBuffPtr;   /*!< Pointer to CRYP processing (encryption, decryption,...) buffer */
    uint32_t                        *pCrypOutBuffPtr;  /*!< Pointer to CRYP processing (encryption, decryption,...) buffer */

    __IO uint16_t                   CrypInCount;   /*!< Counter of inputed data */
    __IO uint16_t                   CrypOutCount;  /*!< Counter of outputed data */

} HAL_CRYP_Handle_TypeDef;

/**
 *  The configuration of Encryption
 */
typedef struct
{
    uint32_t            *pInput;            /**< The encrypted/un-encrypte data Input    */
    uint32_t            *pOutput;           /**< The encrypted/un-encrypte data Output    */
    uint16_t            length;             /**< Size Length of the plaintext buffer, must be a multiple of 16 */
    int16_t             timeout;            /**< Timeout value */

    HAL_CRYP_Mode_TypeDef   cryp_mode;      /**< Cryp mode @ref HAL_CRYP_Mode_TypeDef */

} HAL_CRYP_Encrypt_Cfg_TypeDef;

/**
 *  The configuration of Decryption
 */
typedef HAL_CRYP_Encrypt_Cfg_TypeDef    HAL_CRYP_Decrypt_Cfg_TypeDef;


/**
  * @}
  */ /* End of group CRYP_Exported_Types */

//=============================================================================
//                  Macro Definition
//=============================================================================
/** @defgroup CRYP_Exported_Macros CRYP Exported Macros
  * @{
  */

/**
 *  \brief  Enable/Disable the CRYP module
 *
 *  \param [in] __HANDLE__      The pointer of a CRYP handle
 *  \return                     None
 */
#define __HAL_CRYP_ENABLE(__HANDLE__)       \
            SET_BIT((__HANDLE__)->Instance->CR, AES_CR_EN)

#define __HAL_CRYP_DISABLE(__HANDLE__)      \
            CLEAR_BIT((__HANDLE__)->Instance->CR, AES_CR_EN)


/**
 *  \brief  Returns the CRYP state
 *
 *  \param [in] __HANDLE__      The pointer of a CRYP handle
 *  \return                     HAL state, @ref HAL_CRYP_State_TypeDef
 */
#define __HAL_CRYP_GET_STATE(__HANDLE__)    \
            (__HANDLE__)->State

/**
 *  \brief  Set CRYP mode
 *
 *  \param [in] __HANDLE__      The pointer of a CRYP handle
 *  \param [in] __MODE__        The target Algorithm Mode, @ref HAL_CRYP_ALGO_MODE_TypeDef
 *  \return                     None
 *
 */
#define __HAL_CRYP_SET_MODE(__HANDLE__, __MODE__)    \
            SET_BIT((__HANDLE__)->Instance->CR, (__MODE__))

/**
 *  \brief  Enable the CRYP interrupt.
 *
 *  \param [in] __HANDLE__      The pointer of a CRYP handle
 *  \param [in] __INTERRUPT__   CRYP Interrupt.
 *  \return                     None
 */
#define __HAL_CRYP_ENABLE_IT(__HANDLE__, __INTERRUPT__) \
            SET_BIT((__HANDLE__)->Instance->CR, (__INTERRUPT__))

/**
 *  \brief  Disable the CRYP interrupt.
 *
 *  \param [in] __HANDLE__      The pointer of a CRYP handle
 *  \param [in] __INTERRUPT__   CRYP Interrupt.
 *  \return                     None
 */
#define __HAL_CRYP_DISABLE_IT(__HANDLE__, __INTERRUPT__)    \
            CLEAR_BIT((__HANDLE__)->Instance->CR, (__INTERRUPT__))

/**
 *  \brief  Get CRYP interrupt flag
 *
 *  \param [in] __HANDLE__      The pointer of a CRYP handle
 *  \param [in] __FLAG__        error flag, @ref HAL_CRYP_FLAG_TypeDef
 *  \return
 */
#define __HAL_CRYP_GET_IT_FLAG(__HANDLE__, __FLAG__)   \
            ((__HANDLE__)->Instance->SR & (__FLAG__))

/**
 *  \brief  Clear interrupt flags
 *
 *  \param [in] __HANDLE__      The pointer of a CRYP handle
 *  \param [in] __FLAG__        The flag to clear. @ref HAL_CRYP_CLRFLAG_TypeDef
 *  \return
 *
 */
#define __HAL_CRYP_CLEAR_FLAG(__HANDLE__, __FLAG__)     \
            SET_BIT((__HANDLE__)->Instance->CR, (__FLAG__))

/**
 *  \brief  Get the data input address of Cryp
 *
 *  \param [in] __HANDLE__      The pointer of a CRYP handle
 *  \return                     The address of CRYP data input
 */
#define __HAL_CRYP_GET_DATA_IN_ADDRESS(__HANDLE__)   \
            (&(__HANDLE__)->Instance->DINR)

/**
 *  \brief  Get the data output address of Cryp
 *
 *  \param [in] __HANDLE__      The pointer of a CRYP handle
 *  \return                     The address of CRYP data output
 */
#define __HAL_CRYP_GET_DATA_OUT_ADDRESS(__HANDLE__)  \
            (&(__HANDLE__)->Instance->DOUTR)

/**
  * @}
  */ /* End of group CRYP_Exported_Macros */


//=============================================================================
//                  Public Function Definition
//=============================================================================
/** @addtogroup CRYP_Exported_Functions
  * @{
  */

/**
 *  \brief  Cryp initialize
 *
 *  \param [in] hCryp       pointer to a HAL_CRYP_Handle_TypeDef structure
 *  \return
 *      reference HAL_StatusTypeDef
 */
HAL_StatusTypeDef HAL_CRYP_Init(HAL_CRYP_Handle_TypeDef *hCryp);


/**
 *  \brief  Cryp de-initialize
 *
 *  \param [in] hCryp       pointer to a HAL_CRYP_Handle_TypeDef structure
 *  \return
 *      reference HAL_StatusTypeDef
 */
HAL_StatusTypeDef HAL_CRYP_DeInit(HAL_CRYP_Handle_TypeDef *hCryp);

/**
 *  \brief  Cryp Encrypt data
 *
 *  \param [in] hCryp       pointer to a HAL_CRYP_Handle_TypeDef structure
 *  \param [in] pCfg        pointer to a HAL_CRYP_Encrypt_Cfg_TypeDef structure
 *  \return
 *      reference HAL_StatusTypeDef
 */
HAL_StatusTypeDef
HAL_CRYP_AES_Encrypt(
    HAL_CRYP_Handle_TypeDef         *hCryp,
    HAL_CRYP_Encrypt_Cfg_TypeDef    *pCfg);


/**
 *  \brief  Cryp Decrypt data
 *
 *  \param [in] hCryp       pointer to a HAL_CRYP_Handle_TypeDef structure
 *  \param [in] pCfg        pointer to a HAL_CRYP_Decrypt_Cfg_TypeDef structure
 *  \return
 *      reference HAL_StatusTypeDef
 */
HAL_StatusTypeDef
HAL_CRYP_AES_Decrypt(
    HAL_CRYP_Handle_TypeDef         *hCryp,
    HAL_CRYP_Decrypt_Cfg_TypeDef    *pCfg);


/**
 *  \brief  Cryp Encrypt data with interrupt
 *
 *  \param [in] hCryp       pointer to a HAL_CRYP_Handle_TypeDef structure
 *  \param [in] pCfg        pointer to a HAL_CRYP_Decrypt_Cfg_TypeDef structure
 *  \return
 *      reference HAL_StatusTypeDef
 */
HAL_StatusTypeDef
HAL_CRYP_AES_Encrypt_IT(
    HAL_CRYP_Handle_TypeDef         *hCryp,
    HAL_CRYP_Encrypt_Cfg_TypeDef    *pCfg);


/**
 *  \brief  Cryp Decrypt data with interrupt
 *
 *  \param [in] hCryp       pointer to a HAL_CRYP_Handle_TypeDef structure
 *  \param [in] pCfg        pointer to a HAL_CRYP_Decrypt_Cfg_TypeDef structure
 *  \return
 *       reference HAL_StatusTypeDef
 */
HAL_StatusTypeDef
HAL_CRYP_AES_Decrypt_IT(
    HAL_CRYP_Handle_TypeDef         *hCryp,
    HAL_CRYP_Encrypt_Cfg_TypeDef    *pCfg);


/**
 *  \brief  Cryp Encrypt data with DMA
 *
 *  \param [in] hCryp       pointer to a HAL_CRYP_Handle_TypeDef structure
 *  \param [in] pCfg        pointer to a HAL_CRYP_Decrypt_Cfg_TypeDef structure
 *  \return
 *      reference HAL_StatusTypeDef
 */
HAL_StatusTypeDef
HAL_CRYP_AES_Encrypt_DMA(
    HAL_CRYP_Handle_TypeDef         *hCryp,
    HAL_CRYP_Encrypt_Cfg_TypeDef    *pCfg);


/**
 *  \brief  Cryp Decrypt data with DMA
 *
 *  \param [in] hCryp       pointer to a HAL_CRYP_Handle_TypeDef structure
 *  \param [in] pCfg        pointer to a HAL_CRYP_Decrypt_Cfg_TypeDef structure
 *  \return
 *      reference HAL_StatusTypeDef
 */
HAL_StatusTypeDef
HAL_CRYP_AES_Decrypt_DMA(
    HAL_CRYP_Handle_TypeDef         *hCryp,
    HAL_CRYP_Encrypt_Cfg_TypeDef    *pCfg);


/**
 *  \brief  Generate key with AES key schedule
 *
 *  \param [in] hCryp           pointer to a HAL_CRYP_Handle_TypeDef structure
 *  \param [in] pKey            pointer to the key used for encryption/decryption, it MUST be 16 characters
 *  \param [in] pKeyDerived     pointer to the buffer of key derivation,
                                    the buffer size of pKeyDerived MUST be the same with key_length
 *  \param [in] key_length      the key (buffer) length of pKey and pKeyDerived, it MUST be a multiple of 16
 *  \return
 *      reference HAL_StatusTypeDef
 */
HAL_StatusTypeDef
HAL_CRYP_AES_Key_Derivation(
    HAL_CRYP_Handle_TypeDef     *hCryp,
    uint32_t                    *pKey,
    uint32_t                    *pKeyDerived,
    int                         key_length);


/**
 *  \brief  Interrupt handler of CRYP
 *
 *  \param [in] hCryp       pointer to a HAL_CRYP_Handle_TypeDef structure
 *  \return                 None
 */
void HAL_CRYP_IRQHandler(HAL_CRYP_Handle_TypeDef *hCryp);


/**
  * @}
  */ /* End of group CRYP_Exported_Functions */

/**
  * @}
  */ /* End of group CRYP */

/**
  * @}
  */ /* End of group ZB32L03x_HAL_Driver */


#ifdef __cplusplus
}
#endif

#endif
